library ieee;
use ieee.std_logic_1164.all;
use IEEE.NUMERIC_STD.all;
use work.typeDefinitions.all;

entity cpuStruct is
  port (
    -- clock signal
    CLK      : in  std_logic;
    -- reset for processor
    nReset   : in  std_logic;
    -- halt for processor
    halt     : out std_logic;
    ramAddr  : out std_logic_vector(15 downto 0);
    ramData  : out std_logic_vector(31 downto 0);
    ramWen   : out std_logic;
    ramRen   : out std_logic;
    ramQ     : in  std_logic_vector(31 downto 0);
    ramState : in  std_logic_vector(1 downto 0)
    );

end cpuStruct;



architecture cpuStruct_arch of cpuStruct is
  
  component SuperArbiter
    port
      (
        -- clk, active-low reset
        clk, nReset  : in  std_logic;
        -- memory signals (in order)
        memAddr      : out std_logic_vector(15 downto 0);  -- mem address being read/written
        memWriteData : out std_logic_vector(31 downto 0);  -- mem data to be written
        memWEN       : out std_logic;   -- write enable
        memREN       : out std_logic;   -- read enable
        memReadData  : in  std_logic_vector(31 downto 0);  -- mem data to be read
        memState     : in  std_logic_vector(1 downto 0);   -- state of mem
        -- Core 1 Arbiter signals (in order)
        a1Addr       : in  std_logic_vector(15 downto 0);  -- mem address being read/written
        a1WriteData  : in  std_logic_vector(31 downto 0);  -- mem data to be written
        a1WEN        : in  std_logic;   -- write enable
        a1REN        : in  std_logic;   -- read enable
        a1ReadData   : out std_logic_vector(31 downto 0);  -- mem data to be read
        a1State      : out std_logic_vector(1 downto 0);   -- state of mem
        -- Core 2 Arbiter signals (in order)
        a2Addr       : in  std_logic_vector(15 downto 0);  -- mem address being read/written
        a2WriteData  : in  std_logic_vector(31 downto 0);  -- mem data to be written
        a2WEN        : in  std_logic;   -- write enable
        a2REN        : in  std_logic;   -- read enable
        a2ReadData   : out std_logic_vector(31 downto 0);  -- mem data to be read
        a2State      : out std_logic_vector(1 downto 0)    -- state of mem
        );
  end component;

  component coco
    port
      (
        clk, nReset : in std_logic;

        --what 1 is transmitting
        TxBusOp1   : in memBusOp;
        TxBusAddr1 : in std_logic_vector(31 downto 0);
        TxBusResp1 : in memBusResp;
        TxBusData1 : in std_logic_vector(63 downto 0);

        --what 1 is receiving
        RxBusOp1   : out memBusOp;
        RxBusAddr1 : out std_logic_vector(31 downto 0);
        RxBusResp1 : out memBusResp;
        RxBusData1 : out std_logic_vector(63 downto 0);

        --dcache 2 signals

        --what 2 is transmitting
        TxBusOp2   : in memBusOp;
        TxBusAddr2 : in std_logic_vector(31 downto 0);
        TxBusResp2 : in memBusResp;
        TxBusData2 : in std_logic_vector(63 downto 0);

        --what 2 is receiving
        RxBusOp2   : out memBusOp;
        RxBusAddr2 : out std_logic_vector(31 downto 0);
        RxBusResp2 : out memBusResp;
        RxBusData2 : out std_logic_vector(63 downto 0)
        );
  end component;

  component cpuCore port (
    -- clock signal
    CLK          : in  std_logic;
    -- reset for processor
    nReset       : in  std_logic;
    -- halt for processor
    halt         : out std_logic;
    -- default PC for this CPU
    defaultPC    : in  std_logic_vector(31 downto 0);
    -- mem signals
    memAddr      : out std_logic_vector(15 downto 0);  -- mem address being read/written
    memWriteData : out std_logic_vector(31 downto 0);  -- mem data to be written
    memWEN       : out std_logic;       -- write enable
    memREN       : out std_logic;       -- read enable
    memReadData  : in  std_logic_vector(31 downto 0);  -- mem data to be read
    memState     : in  std_logic_vector(1 downto 0);    -- state of mem
    -- coherency BS
    TxBusOp      : out memBusOp;
    TxBusAddr    : out std_logic_vector(31 downto 0);
    TxBusResp    : out memBusResp;
    TxBusData    : out std_logic_vector(63 downto 0);
    RxBusOp      : in  memBusOp;
    RxBusAddr    : in  std_logic_vector(31 downto 0);
    RxBusResp    : in  memBusResp;
    RxBusData    : in  std_logic_vector(63 downto 0)
    );

  end component;


  signal t_halt1, t_halt2 : std_logic;
  signal arb1, arb2       : memSignal;  --arbiter to superarb
                                        --

  signal bus1, bus2 : dcacheBus;

--signal forward : forwardSignals;

begin  -- cpuStruct_arch

  halt <= t_halt1 and t_halt2;


  supera_c : SuperArbiter port map
    (
      clk    => clk,
      nReset => nReset,

      memAddr      => ramAddr,
      memWriteData => ramData,
      memWEN       => ramWen,
      memREN       => ramRen,
      memReadData  => ramQ,
      memState     => ramState,

      a1Addr      => arb1.addr,
      a1WriteData => arb1.wData,
      a1WEN       => arb1.wEN,
      a1REN       => arb1.rEN,
      a1ReadData  => arb1.rData,
      a1State     => arb1.state,

      a2Addr      => arb2.addr,
      a2WriteData => arb2.wData,
      a2WEN       => arb2.wEN,
      a2REN       => arb2.rEN,
      a2ReadData  => arb2.rData,
      a2State     => arb2.state
      );

  coco_c : coco port map
    (
      clk    => clk,
      nReset => nReset,

      TxBusOp1   => bus1.TxOp,
      TxBusAddr1 => bus1.TxAddr,
      TxBusResp1 => bus1.TxResp,
      TxBusData1 => bus1.TxData,

      RxBusOp1   => bus1.RxOp,
      RxBusAddr1 => bus1.RxAddr,
      RxBusResp1 => bus1.RxResp,
      RxBusData1 => bus1.RxData,

      TxBusOp2   => bus2.TxOp,
      TxBusAddr2 => bus2.TxAddr,
      TxBusResp2 => bus2.TxResp,
      TxBusData2 => bus2.TxData,

      RxBusOp2   => bus2.RxOp,
      RxBusAddr2 => bus2.RxAddr,
      RxBusResp2  => bus2.RxResp,
      RxBusData2 => bus2.RxData
      );

  core1_c : cpuCore port map(

    CLK    => clk,
    nReset => nReset,
    halt   => t_halt1,

    defaultPC    => x"00000000",
    memAddr      => arb1.addr,
    memWriteData => arb1.wData,
    memWEN       => arb1.wEN,
    memREN       => arb1.rEN,
    memReadData  => arb1.rData,
    memState     => arb1.state,

    TxBusOp   => bus1.TxOp,
    TxBusAddr => bus1.TxAddr,
    TxBusResp => bus1.TxResp,
    TxBusData => bus1.TxData,
    RxBusOp   => bus1.RxOp,
    RxBusAddr => bus1.RxAddr,
    RxBusResp => bus1.RxResp,
    RxBusData => bus1.RxData
    );

   core2_c : cpuCore port map(

    CLK    => clk,
    nReset => nReset,
    halt   => t_halt2,

    defaultPC    => x"00000200",
    memAddr      => arb2.addr,
    memWriteData => arb2.wData,
    memWEN       => arb2.wEN,
    memREN       => arb2.rEN,
    memReadData  => arb2.rData,
    memState     => arb2.state,

    TxBusOp   => bus2.TxOp,
    TxBusAddr => bus2.TxAddr,
    TxBusResp => bus2.TxResp,
    TxBusData => bus2.TxData,
    RxBusOp   => bus2.RxOp,
    RxBusAddr => bus2.RxAddr,
    RxBusResp => bus2.RxResp,
    RxBusData => bus2.RxData
    );

end cpuStruct_arch;
